/*******************************************************
 * Title: BaseConfig.java 
 * Description: 
 * 
 * Copyright 2009. silverduner.com. 
 * All rights reserved.
 *******************************************************/
package com.silverduner.config;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.DefaultConfigurationBuilder;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.tree.ExpressionEngine;
import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author Yuwen Sun
 * @version 
 */
public class DefaultConfigImpl implements Config {
	private static final Log logger = LogFactory.getLog(DefaultConfigImpl.class);
	private static final ExpressionEngine DEFAULT_EXPRESSION_ENGINE = new XPathExpressionEngine();
	
	private HierarchicalConfiguration _config = null;
	
	public DefaultConfigImpl(URL url) throws ConfigException{
		DefaultConfigurationBuilder builder = new DefaultConfigurationBuilder();
		builder.setURL(url);
		try {
			_config=builder.getConfiguration(true);
			_config.setExpressionEngine(DEFAULT_EXPRESSION_ENGINE);
			_config.setDelimiterParsingDisabled(true);
		} catch (ConfigurationException e) {
			logger.error(e);
			throw new ConfigException(e.getMessage());
		}
	}

	private DefaultConfigImpl(HierarchicalConfiguration config){
		_config=config;
	}

	public boolean containsKey(String key) {
		return _config.containsKey(key);
	}

	public BigDecimal getBigDecimal(String key) {
		return _config.getBigDecimal(key);
	}

	public BigDecimal getBigDecimal(String key, BigDecimal defaultValue) {
		return _config.getBigDecimal(key, defaultValue);
	}

	public BigInteger getBigInteger(String key) {
		return _config.getBigInteger(key);
	}

	public BigInteger getBigInteger(String key, BigInteger defaultValue) {
		return _config.getBigInteger(key, defaultValue);
	}

	public boolean getBoolean(String key) {
		return _config.getBoolean(key);
	}

	public boolean getBoolean(String key, boolean defaultValue) {
		return _config.getBoolean(key, defaultValue);
	}

	public Boolean getBoolean(String key, Boolean defaultValue) {
		return _config.getBoolean(key, defaultValue);
	}

	public byte getByte(String key) {
		return _config.getByte(key);
	}

	public byte getByte(String key, byte defaultValue) {
		return _config.getByte(key, defaultValue);
	}

	public Byte getByte(String key, Byte defaultValue) {
		return _config.getByte(key, defaultValue);
	}

	public double getDouble(String key) {
		return _config.getDouble(key);
	}

	public double getDouble(String key, double defaultValue) {
		return _config.getDouble(key, defaultValue);
	}

	public Double getDouble(String key, Double defaultValue) {
		return _config.getDouble(key, defaultValue);
	}

	public float getFloat(String key) {
		return _config.getFloat(key);
	}

	public float getFloat(String key, float defaultValue) {
		return _config.getFloat(key, defaultValue);
	}

	public Float getFloat(String key, Float defaultValue) {
		return _config.getFloat(key, defaultValue);
	}

	public int getInt(String key) {
		return _config.getInt(key);
	}

	public int getInt(String key, int defaultValue) {
		return _config.getInt(key, defaultValue);
	}

	public Integer getInteger(String key, Integer defaultValue) {
		return _config.getInteger(key, defaultValue);
	}

	@SuppressWarnings("unchecked")
	public List getList(String key) {
		return _config.getList(key);
	}

	@SuppressWarnings("unchecked")
	public List getList(String key, List defaultValue) {
		return _config.getList(key, defaultValue);
	}

	public long getLong(String key) {
		return _config.getLong(key);
	}

	public long getLong(String key, long defaultValue) {
		return _config.getLong(key, defaultValue);
	}

	public Long getLong(String key, Long defaultValue) {
		return _config.getLong(key, defaultValue);
	}

	public Properties getProperties(String key) {
		return _config.getProperties(key);
	}

	public short getShort(String key) {
		return _config.getShort(key);
	}

	public short getShort(String key, short defaultValue) {
		return _config.getShort(key, defaultValue);
	}

	public Short getShort(String key, Short defaultValue) {
		return _config.getShort(key, defaultValue);
	}

	public String getString(String key) {
		return _config.getString(key);
	}

	public String getString(String key, String defaultValue) {
		return _config.getString(key, defaultValue);
	}

	public String[] getStringArray(String key) {
		return _config.getStringArray(key);
	}

	public boolean isEmpty() {
		return _config.isEmpty();
	}

	public Config subConfig(String key) {
		return new DefaultConfigImpl(_config.configurationAt(key));
	}

	@SuppressWarnings("unchecked")
	public Map<String, Config> subConfigMap(String idKey, String key) {
		HashMap<String,Config> configMap =new HashMap<String,Config>();
		List<HierarchicalConfiguration> configList = (List<HierarchicalConfiguration>)_config.configurationsAt(key);
		String id=null;
		for(HierarchicalConfiguration config : configList){
			id = config.getString(idKey);
			if(StringUtils.isEmpty(id))
				logger.warn("can not find identify key '"+idKey+"' in config: "+config);
			else
				configMap.put(id, new DefaultConfigImpl(config));
		}
		return configMap;
	}

}
